<?php
/**
 * Example.php for BaseZF in /includes/BaseZF
 *
 * @category   BaseZF
 * @package    BaseZF
 * @copyright  Copyright (c) 2004-2007 Harold Thétiot
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */

class BaseZF_Example extends BaseZF_Base
{
    /**
     * Unique Id
     */
    private $_id_example;

    /**
     * Data
     */
    protected $_data;

    /**
     * Constructor
     *
     * @param integer $_id_example Example Id
     */
    public function __construct($id_example = null)
    {
        $this->_id_example = (int) $id_example;
    }

    /**
     * Getter for id_example
     *
     * @return integer Example Id
     */
    public function getExampleId()
    {
        return $this->_id_example;
    }

    /**
     * Check if object is properly instancied
     *
     * @throw Exception
     * @param boolean $return_exception use Exception ?
     * @return boolean True if current object is is properly instancied
     */
    private function _isInstancied($return_exception = true)
    {
        if(!$this->getExampleId())  {
            $return = false;
        } else {
            $return = true;
        }

        if ($return_exception && !$return) {
            throw new Exception('Example Object is not associated to an id_example');
        }

        return $return;
    }

    /**
     * Search Example with or without filter and pagination options
     *
     * @param integer $current_page current page
     * @param integer $nb_per_page nbr of result by page
     * @param array $property_filters filter possibility
     * @param string $sort_field use to order the result
     * @param string $sort_order ASC / DESC
     *
     * @return array of str object example
     */
    static public function search($current_page = 1, $nb_per_page = null, $property_filters = array(), $sort_field = null, $sort_order = null) {

        //get conn
        $conn = BaseZF::registry('conn');

         //check page value
        if((int) $current_page <= 0) {
            $current_page = 1;
        }

        //set some var
        $filter_values = array();
        $add_table_values = array();
        $query_limit = null;
        $query_offset = null;
        $offset = null;

        //set return var
        $return = array();
        $return['nb_results'] = 0;
        $return['nb_pages'] = 0;
        $return['current_page'] = $current_page;
        $return['nb_per_page'] = $nb_per_page;
        $return['results'] = array();

        //set filter
        if(isset($property_filters['id_example'])) {
            $filter_values['id_example'] = $conn->quoteInto('AND example.id_example = ?', (int) $property_filters['id_example']);
        }

        // set filter
        $filters = implode("\n ", $filter_values);
        $add_tables = implode("\n ", $add_table_values);

        if ($nb_per_page > 0) {

            //count query
            $query = '
            SELECT
                count(example.id_example) as nb_results
            FROM
                example
                ' . $add_tables . '
            WHERE TRUE
                ' . $filters . '
            ;';

            //exec sql
            $stmt = self::getStatement($query);
            $stmt->execute();
            $db_data = $stmt->fetch();

            //set some return : nb_result and nb_pages
            $return['nb_results'] = $db_data['nb_results'];
            $return['nb_pages'] = ceil($return['nb_results'] / $nb_per_page);

            //set the offset
            $offset = (((int) $current_page) - 1) * (int) $nb_per_page;
            $query_limit = 'OFFSET :offset';
            $query_offset = 'LIMIT :limit';
        }


        if ($return['nb_results'] > 0 || $nb_per_page == null) {

            //set order by
            $default_sort_field = 'example.id_example';
            if (empty($sort_field) || ($toto = self::_getTableForPropertyModification($sort_field)) === false) {
                $sort_field = $default_sort_field;
            }

            if (!in_array($sort_order, array('ASC', 'DESC'))) {
                $sort_order = 'ASC';
            }

            //select query
            $query = '
                SELECT
                    example.id_example
                FROM
                    example
                    ' . $add_tables . '
                WHERE TRUE
                    ' . $filters . '
                ORDER BY ' . $sort_field . ' ' . $sort_order . '
                ' . $query_limit . '
                ' . $query_offset . '
            ;';

            $stmt = self::getStatement($query);

            if (!empty($query_offset)) {
                $stmt->bindValue(':offset', $offset);
            }

            if (!empty($query_limit)) {
                $stmt->bindValue(':limit', $nb_per_page);
            }

            $stmt->execute();

            while ($row = $stmt->fetch()) {
                $return['results'][] = new BaseZF_Example($row['id_example']);
            }

            if (is_null($nb_per_page)) {
                $return['nb_results'] = count($return['results']);
            }
        }

		$return['sort_field'] = $sort_field;
		$return['sort_order'] = $sort_order;

        return (object) $return;
    }

    /**
     * Get Example data and set in cache
     *
     * @throw BaseZF_Exception
     * @return array Data
     */
    private function _getData()
    {
        // ckeck if properly instancied
        $this->_isInstancied();

        // set used cache key
        $cacheKey = 'example:' . $this->getExampleId() . ':data';

        try {
            // retrieve form cache
            $example_data = $this->getFromCache($cacheKey);
        } catch (BaseZF_Framework_Cache_Exception $e) {

            // retrieve form db
            $query = "
                SELECT
                   example.name,
                   example.description,
                   example.creation,
                   EXTRACT(EPOCH FROM example.creation) as creation_timestamp,
                   example.email,
                   example.active

                FROM
                    example
                WHERE TRUE
                    AND id_example = :id_example
                ;
                ";

            $stmt = self::getStatement($query);
            $stmt->bindValue(':id_example', $this->getExampleId());
            $stmt->execute();

            $example_data = array();
            if ($row = $stmt->fetch()) {
                foreach ($row as $k => $v) {
                    if (is_null($v)) {
                        $example_data[$k] = '';
                    } else {
                        $example_data[$k] = $v;
                    }
                }
            } else {
                throw new BaseZF_Exception('Example not found for id_example "' . $this->getExampleId() . '"');
            }

            $this->setInCache($cacheKey, $example_data);
        }

        $this->_data = $example_data;

        return $this->_data;
    }

    /**
     * Static validate Exemple Data before insert or update
     *
     * @param array $params property to update or insert
     * @param boolean $return_exception true if must use Exception
     * @return boolean validate result
     */
    public static function validateForCreation($params, $return_exception = false)
    {
		$tmp_example = new BaseZF_Example();
		$params_errors = $tmp_example->validate($params, $return_exception);
		unset($tmp_example);

		// check params_errors
        if (count($params_errors) > 0 && $return_exception) {
            throw new BaseZF_Exception('Unable to validate new params : ' . var_export($params_errors, true));
        }

		return $params_errors;
    }

	/**
     * validate Example Data before update
     *
     * @param array $params property to update or insert
     * @param boolean $return_exception true if must use Exception
     * @return boolean validate result
     */
    public function validateForModification($params, $return_exception = false)
    {
        $params_errors = $this->validate($params);

		// check params_errors
        if (count($params_errors) > 0 && $return_exception) {
            throw new BaseZF_Exception('Unable to validate new params : ' . var_export($params_errors, true));
        }

		return $params_errors;
	}

    /**
     * validate Example Data before insert or update
     *
     * @param array $params property to update or insert
     * @param boolean $return_exception true if must use Exception
     * @return boolean validate result
     */
    public function validate($params, $return_exception = false)
    {
        $params_types = array(
            'name'          => array('notags', 'notempty'),
            'description'   => 'notags',
            'creation'      => array('datetime', 'notempty'),
            'email'         => 'email',
            'active'        => 'boolean',
        );

        $params_errors = $this->checkByType($params, $params_types);

        if (count($params_errors) > 0 && $return_exception) {
            throw new BaseZF_Exception('Unable to validate new params : ' . var_export($params_errors, true));
        }

        return $params_errors;
    }

    /**
     * Create a new Example and insert data in DB
     *
     * @param array $params property
     * @return object new BaseZF_Example object
     */
    static public function createNew($params)
    {
        //get conn
        $conn = BaseZF::registry('conn');

        //test insered params
        self::validateForCreation($params, true);

        // insert db data
        $conn->insert('example', $params);

        //build a new object
        $new_example = new BaseZF_Example($conn->lastInsertId('example_id_example_seq'));

        return $new_example;
    }

    /**
     * Update Example data
     *
     * @throw BaseZF_Exception
     * @param array $params changed property
     * @return boolean update result
     */
    public function updateData($params)
    {
        // ckeck if properly instancied
        $this->_isInstancied();

        //test insered params
        $this->validateForModification($params, true);

        //set modified param
        foreach ($params as $key => $value) {
            //set new property value
            $this->modifyProperty($key, $value);
            $this->_data[$key] = $value;
        }

        $r = $this->saveModifiedProperties();

        return $r;
    }

    /**
     * Remove Example data in DB and cache
     *
     * @return boolean delete result
     */
    public function delete()
    {
        // ckeck if properly instancied
        $this->_isInstancied();

        $query = "
            DELETE FROM
                example
            WHERE TRUE
                AND id_example = :id_example
            ;
        ";

        $stmt = self::getStatement($query);
        $stmt->bindValue(':id_example', $this->getExampleId());
        $stmt->execute();

        $this->flushFromCache();
    }

    /**
     * Get a property, call the correct method to retrieve it
     *
     * @throw BaseZF_Exception
     * @return mixed Property value
     */
    public function __get($property)
    {
        // ckeck if properly instancied
        $this->_isInstancied();

        if (isset($this->_data[$property])) {
            return $this->_data[$property];
        }

        switch ($property) {
            case 'name':
            case 'description': 
            case 'creation':
            case 'creation_timestamp':
            case 'email':
            case 'active':
                $this->_getData();
                break;
           
            default:
                throw new BaseZF_Exception('No property available: "' . $property . '"');
        }

        if (isset($this->_data[$property])) {
            return $this->_data[$property];
        }

        throw new BaseZF_Exception('No property available: "' . $property . '"');
    }

    /**
     * Return all keys which can be in cache
     *
     * @return array Keys array
     */
    protected function _getCacheKeysToDelete()
    {
        $a = array(
            'example:' . $this->getExampleId() . ':data',
        );

        return $a;
    }

     /**
     * Get the table name for the property
     *
     * @param string $property Property name
     * @return string Table name
     */
    static protected function _getTableForPropertyModification($property)
    {
        $possibleProperties = array(
            'name'         => 'example',
            'description'  => 'example',
            'creation'     => 'example',
            'email'        => 'example',
            'active'       => 'example',
        );

        if (isset($possibleProperties[$property])) {
            return $possibleProperties[$property];
        } else {
            return false;
        }
    }

    /**
     * Get the where clause to update tables
     *
     * @return string The quoted where clause
     */
    protected function _getWhereForPropertyModification()
    {
        $conn = BaseZF::registry('conn');
        return $conn->quoteInto('id_example = ?', $this->getExampleId());
    }
}

